#include "myfunc.h"



//**********************************************************************************
//	从json文件中提取出order info 
//**********************************************************************************
bool json_to_order_page(const char *json,struct order_page *op){
//printf("%s\n",json);
	cJSON *total_info=NULL;		//long
	cJSON *orders_data=NULL;	//long
	cJSON *order_info=NULL;
	cJSON *id=NULL;
	cJSON *tb_order_id=NULL;
	cJSON *operate=NULL;
	cJSON *start_date=NULL;
	cJSON *end_date=NULL;
	cJSON *start_time=NULL;
	cJSON *end_time=NULL;
	cJSON *days=NULL;
	cJSON *order_type_name=NULL;
	cJSON *order_type=NULL;
	cJSON *channel=NULL;
	cJSON *antenna_prog_id=NULL;	//int
	cJSON *freq=NULL;		//int
	cJSON *azimuth=NULL;
	cJSON *actual_power=NULL;
	cJSON *op_status=NULL;
	cJSON *trans_name=NULL;
	cJSON *ant_used_code=NULL;
	cJSON *reason=NULL;
	cJSON *station_name=NULL;
	cJSON *prog_desc=NULL;
	cJSON *program_name=NULL;
	cJSON *ant_prog_desc=NULL;
	cJSON *feedback_status=NULL;
	cJSON *actual_start=NULL;
	cJSON *mod=NULL;
	total_info=cJSON_Parse(json);
	if(total_info != NULL){	//	json_txt is valid
		orders_data=cJSON_GetObjectItemCaseSensitive(total_info,"data");
		int array_size=cJSON_GetArraySize(orders_data);
		struct order_info order_info_stc;
		memset(&order_info_stc,0,sizeof(struct order_info));
		for(int i=0;i<array_size;i++){
			order_info	=cJSON_GetArrayItem(orders_data,i);
			id		=cJSON_GetObjectItem(order_info,"id");
			operate		=cJSON_GetObjectItem(order_info,"operate");
			start_date	=cJSON_GetObjectItem(order_info,"startDate");
			end_date	=cJSON_GetObjectItem(order_info,"endDate");
			start_time	=cJSON_GetObjectItem(order_info,"startTime");
			end_time	=cJSON_GetObjectItem(order_info,"endTime");
			days		=cJSON_GetObjectItem(order_info,"days");
			order_type_name	=cJSON_GetObjectItem(order_info,"orderTypeName");
			order_type	=cJSON_GetObjectItem(order_info,"orderType");
			channel		=cJSON_GetObjectItem(order_info,"channel");
			antenna_prog_id	=cJSON_GetObjectItem(order_info,"antennaProgId");
			freq		=cJSON_GetObjectItem(order_info,"freq");
			azimuth		=cJSON_GetObjectItem(order_info,"azimuthM");
			actual_power	=cJSON_GetObjectItem(order_info,"actualPower");
			op_status	=cJSON_GetObjectItem(order_info,"opStatus");
			trans_name	=cJSON_GetObjectItem(order_info,"transName");
			ant_used_code	=cJSON_GetObjectItem(order_info,"antUsedCode");
			reason		=cJSON_GetObjectItem(order_info,"reason");
			station_name	=cJSON_GetObjectItem(order_info,"stationName");
			prog_desc	=cJSON_GetObjectItem(order_info,"progDesc");
			program_name	=cJSON_GetObjectItem(order_info,"programName");
			ant_prog_desc	=cJSON_GetObjectItem(order_info,"anProgDesc");
			feedback_status	=cJSON_GetObjectItem(order_info,"feedbackStatus");
			actual_start	=cJSON_GetObjectItem(order_info,"actualStart");
			tb_order_id	=cJSON_GetObjectItem(order_info,"tbOrderId");
			mod		=cJSON_GetObjectItem(order_info,"mod");
			//*******************************************************************
			//
			//*******************************************************************
			order_info_stc.id=		cJSON_GetNumberValue(id);
			order_info_stc.tb_order_id=	cJSON_GetNumberValue(tb_order_id);
			strcpy(order_info_stc.operate,	cJSON_GetStringValue(operate));
			strcpy(order_info_stc.start_date,	cJSON_GetStringValue(start_date));
			strcpy(order_info_stc.end_date,		cJSON_GetStringValue(end_date));
			strcpy(order_info_stc.start_time,	cJSON_GetStringValue(start_time));
			strcpy(order_info_stc.end_time,		cJSON_GetStringValue(end_time));
			strcpy(order_info_stc.days,		cJSON_GetStringValue(days));
			strcpy(order_info_stc.order_type_name,	cJSON_GetStringValue(order_type_name));
			strcpy(order_info_stc.order_type,	cJSON_GetStringValue(order_type));
			strcpy(order_info_stc.channel,		cJSON_GetStringValue(channel));
			order_info_stc.antenna_prog_id=	cJSON_GetNumberValue(antenna_prog_id);
			order_info_stc.freq=		cJSON_GetNumberValue(freq);
			strcpy(order_info_stc.azimuth,		cJSON_GetStringValue(azimuth));
			strcpy(order_info_stc.actual_power,	cJSON_GetStringValue(actual_power));
			if(op_status!=NULL)
				strcpy(order_info_stc.op_status,	cJSON_GetStringValue(op_status));
			else
				strcpy(order_info_stc.op_status,"");
			strcpy(order_info_stc.trans_name,	cJSON_GetStringValue(trans_name));
			strcpy(order_info_stc.ant_used_code,	cJSON_GetStringValue(ant_used_code));
			strcpy(order_info_stc.reason,		cJSON_GetStringValue(reason));
			strcpy(order_info_stc.station_name,	cJSON_GetStringValue(station_name));
			strcpy(order_info_stc.prog_desc,	cJSON_GetStringValue(prog_desc));
			strcpy(order_info_stc.program_name,	cJSON_GetStringValue(program_name));
			strcpy(order_info_stc.ant_prog_desc,	cJSON_GetStringValue(ant_prog_desc));
			if(feedback_status!=NULL)
				strcpy(order_info_stc.feedback_status,	cJSON_GetStringValue(feedback_status));
			else
				strcpy(order_info_stc.feedback_status,"");
			strcpy(order_info_stc.actual_start,	cJSON_GetStringValue(actual_start));
			strcpy(order_info_stc.mod,		cJSON_GetStringValue(mod));
			//	添加调度令到调单中
			add_orders(op->orders,&order_info_stc);
			memset(&order_info_stc,0,sizeof(struct order_info));
		}
		cJSON_Delete(total_info);
		return true;
	}
	else{
printf("parse error\n");
		cJSON_Delete(total_info);
		return false;
	}
}


void kill_cr_lf(char *dst,char *src){
	if(src==NULL)return;
	int len=strlen(src);
	char c;
	for(int i=0;i<len;i++){
		c=src[i];
		if(c!='\r' && c!='\n' && c!='\t')
			*(dst++)=c;
	}
	*dst='\0';
	return;
}


//***********************************************************************************
//	查找{\"receive\":[],\"feedBack\":[]} json数据
//***********************************************************************************
char *find_match_json_string(struct data_buffer *input,char *noodle,
		size_t *strlen){
	const char *haystack;
	char *begin;
	char *tail;
	haystack=input->contentPtr;
	//查找 noodle 开头的数据
	begin=strstr(haystack,noodle);
	tail=begin;
	if(!begin)return NULL;
	//	found string
	int brace_match=0;
	bool match=false;
	while(*tail != '\0'){
		if(*tail=='{')
			brace_match++;
		else if(*tail=='}')
			brace_match--;
		else{}
		tail++;
		if(brace_match==0){//brace match !!!
			match=true;
			break;		 
		}
	}
	if(match){
		*strlen=tail-begin;
		return begin;
	}
	else
		return NULL;
}


//************************************************************************************************
//	去除 \" 中的'\'  end with '\0'
//************************************************************************************************
char * kill_slash_before_double_quote(char* target,size_t len){
	if(target==NULL)return NULL;
	//size_t len=strlen(target);
	char *ret=malloc(len+1);
	char *dst=ret;
	char *prev=target;
	target++;
	*(dst++)=*prev;
	while( --len ){
		*dst=*target;
		if( (*target)=='\"' && (*prev)=='\\'){//bingo
			*(--dst)='\"';
		}
		dst++;
		prev=target;
		target++;
	}
	*dst='\0';
	return ret;
}

//*************************************************************************************************
//	从json格式的json_str 中提取出符合stationId=78的id值，压入head队列
//*************************************************************************************************

void find_id_in_json(char *json_str,struct int_queue_node* head){
	cJSON *total_msg;
	const cJSON *receive_arr;
	const cJSON *recv_arr_item;
	const cJSON *feedBack_arr;
	const cJSON *fb_arr_item;
	const cJSON *info;
	const cJSON *id;
	const cJSON *stationId;
	
	int id_number;
	//char *stationID;
	total_msg=cJSON_Parse(json_str);
	if(total_msg==NULL){
		printf("JSON parse error\n");	
		return;
	}
	receive_arr=	cJSON_GetObjectItemCaseSensitive(total_msg,"receive");
	feedBack_arr=	cJSON_GetObjectItemCaseSensitive(total_msg,"feedBack");

	int arr_size=0;
	if(cJSON_IsArray(receive_arr)){
		arr_size=cJSON_GetArraySize(receive_arr);
		for(int i=0;i<arr_size;i++){
			recv_arr_item=cJSON_GetArrayItem(receive_arr,i);
			stationId=cJSON_GetObjectItemCaseSensitive(recv_arr_item,"stationId");
			//if( !strcmp("78",cJSON_GetStringValue(stationId)) ){
				id=cJSON_GetObjectItemCaseSensitive(recv_arr_item,"id");
				id_number=cJSON_GetNumberValue(id);
				in_queue(head,id_number);
			//}
		}
	}
	if(cJSON_IsArray(feedBack_arr)){
		arr_size=cJSON_GetArraySize(feedBack_arr);
		for(int i=0;i<arr_size;i++){
			fb_arr_item=cJSON_GetArrayItem(feedBack_arr,i);
			stationId=cJSON_GetObjectItemCaseSensitive(fb_arr_item,"stationId");
			//if( !strcmp("78",cJSON_GetStringValue(stationId)) ){
				id=cJSON_GetObjectItemCaseSensitive(fb_arr_item,"id");
				id_number=cJSON_GetNumberValue(id);
				in_queue(head,id_number);
			//}
		}
	}
	cJSON_Delete(total_msg);
	return;
}


//*******************************************************************************************
//	从json格式的json_str 中提取出order_page
//*******************************************************************************************
bool get_order_pages_from_json(char *json,struct order_page_node *head){
	cJSON *total_msg;
	const cJSON *receive_arr;
	const cJSON *recv_arr_item;
	const cJSON *feedBack_arr;
	const cJSON *fb_arr_item;
	const cJSON *id;
	const cJSON *year;
	const cJSON *code;
	const cJSON *s_date;
	const cJSON *r_date;
	const cJSON *stationId;
	int id_number;
	total_msg=cJSON_Parse(json);
	if(total_msg==NULL){
		printf("JSON parse error\n");	
		return false;
	}
	receive_arr=	cJSON_GetObjectItemCaseSensitive(total_msg,"receive");
	feedBack_arr=	cJSON_GetObjectItemCaseSensitive(total_msg,"feedBack");
	int arr_size=0;
	if(cJSON_IsArray(receive_arr)){
		arr_size=cJSON_GetArraySize(receive_arr);
		for(int i=0;i<arr_size;i++){
			struct order_page new_page;
			order_page_init(&new_page);
			recv_arr_item=cJSON_GetArrayItem(receive_arr,i);
			//屏蔽该判断，从而获取所有台站的信息
			//if( !strcmp("78",cJSON_GetStringValue(stationId)) ){
			id=		cJSON_GetObjectItemCaseSensitive(recv_arr_item,"id");
			year=		cJSON_GetObjectItemCaseSensitive(recv_arr_item,"orderYear");
			code=		cJSON_GetObjectItemCaseSensitive(recv_arr_item,"orderCode");
			stationId=	cJSON_GetObjectItemCaseSensitive(recv_arr_item,"stationId");
			s_date=		cJSON_GetObjectItemCaseSensitive(recv_arr_item,"sendDate");
			r_date=		cJSON_GetObjectItemCaseSensitive(recv_arr_item,"receiverDateStr");
			new_page.tb_order_id=	cJSON_GetNumberValue(id);
			char *y=		cJSON_GetStringValue(year);
			sscanf(y,"%u",&new_page.order_year);
			strcpy(new_page.station_id,cJSON_GetStringValue(stationId));
			char *code1=cJSON_GetStringValue(code);
			char order_code[10];
			if ( code1 && regex_find(order_code,\
						code1,"[0-9]{5,}") ) {
				strcpy(new_page.order_code,order_code);
			}
			else
				strcpy(new_page.order_code,"");

			char *date=cJSON_GetStringValue(s_date);
			if(date)
				strcpy(new_page.send_date,date);
			else
				strcpy(new_page.send_date,"");

			date=cJSON_GetStringValue(r_date);
			if(date)
				strcpy(new_page.recv_date,date);
			else
				strcpy(new_page.recv_date,"");

			add_order_pages(head,&new_page);
			order_page_destroy(&new_page);
			//}
		}
	}
	else{
		cJSON_Delete(total_msg);
		return false;
	}
	if(cJSON_IsArray(feedBack_arr)){
		arr_size=cJSON_GetArraySize(feedBack_arr);
		for(int i=0;i<arr_size;i++){
			struct order_page new_page;
			order_page_init(&new_page);
			fb_arr_item=cJSON_GetArrayItem(feedBack_arr,i);
			//if( !strcmp("78",cJSON_GetStringValue(stationId)) ){
			id=		cJSON_GetObjectItemCaseSensitive(fb_arr_item,"id");
			year=		cJSON_GetObjectItemCaseSensitive(fb_arr_item,"orderYear");
			code=		cJSON_GetObjectItemCaseSensitive(fb_arr_item,"orderCode");
			stationId=	cJSON_GetObjectItemCaseSensitive(fb_arr_item,"stationId");
			s_date=		cJSON_GetObjectItemCaseSensitive(fb_arr_item,"sendDate");
			r_date=		cJSON_GetObjectItemCaseSensitive(fb_arr_item,"receiverDateStr");
			new_page.tb_order_id=	cJSON_GetNumberValue(id);
			char *y=cJSON_GetStringValue(year);
			sscanf(y,"%u",&new_page.order_year);
			char *code1=cJSON_GetStringValue(code);
			char order_code[10];
			if( code1 && regex_find(order_code,code1,"[0-9]{5,}") ){
				strcpy(new_page.order_code,order_code);
			}
			else
				strcpy(new_page.order_code,"");

			strcpy(new_page.station_id,cJSON_GetStringValue(stationId));
			char *date;
			if( date=cJSON_GetStringValue(s_date) )
				strcpy(new_page.send_date,date);
			else
				strcpy(new_page.send_date,"");

			if( date=cJSON_GetStringValue(r_date) )
				strcpy(new_page.recv_date,date);
			else
				strcpy(new_page.recv_date,"");

			add_order_pages(head,&new_page);
			order_page_destroy(&new_page);
			//}
		}
	}
	else{
		cJSON_Delete(total_msg);
		return false;
	}
	cJSON_Delete(total_msg);
	return true;
}



//**************************************************************************
//
//**************************************************************************

void hex_to_str(unsigned char* str,unsigned char* hex,int len){
	unsigned char high,low;
	for(int i=0;i<len;i++){
		high=hex[i]>>4;
		low=hex[i]&0x0f;
		if( high < 0xa )
			high+=48;
		else
			high+=87;
		if( low < 0xa )
			low+=48;
		else
			low+=87;
		str[2*i]=high;
		str[2*i+1]=low;
	}
	str[2*len]='\0';
}

bool order_page_to_file(struct order_page *op,char *filename){
	FILE *fp;
	fp=fopen(filename,"w");
	if(fp==NULL)return false;
	struct order_page op1;
	struct order_info info;
	duplicate_order_page(&op1,op);
	fwrite(&op1,1,sizeof(struct order_page)-sizeof(\
				struct order_info_node*),fp);
	//print_order_page(&op1);
	while(out_orders(op1.orders,&info)){
		fwrite(&info,1,sizeof(struct order_info),\
				fp);
		memset(&info,0,sizeof(struct order_info));
	}
	order_page_destroy(&op1);
	fclose(fp);
	return true;
}

bool order_page_from_file(struct order_page *op,char *filename){
	FILE *fp;
	struct order_info info;
	fp=fopen(filename,"r");
	if(fp==NULL)return false;
	order_page_init(op);
	fread(op,1,sizeof(struct order_page)-sizeof(struct \
				order_info_node*),fp);

	while(!feof(fp)){
		fread(&info,1,sizeof(struct order_info),fp);
		add_orders(op->orders,&info);
	}
	fclose(fp);
	return true;
}

void print_order_page(struct order_page *op){
	struct order_page op_tmp;
	duplicate_order_page(&op_tmp,op);
	printf("id:%ld [%d]%s station id:%s\n",\
			op_tmp.tb_order_id,op_tmp.order_year,op_tmp.order_code,\
			op_tmp.station_id);
	printf("send date:%s recv date:%s\n",op_tmp.send_date,op_tmp.recv_date);
	struct order_info info;
	while(out_orders(op_tmp.orders,&info)){
		printf("\n\n\n-----------------\n");
		printf("id:%ld\n",info.id);
		printf("tbid:%ld\n",info.tb_order_id);
		printf("operate:%s\n",info.operate);
		printf("start date:%s\n",info.start_date);
		printf("end date:%s\n",info.end_date);
		printf("start time:%s\n",info.start_time);
		printf("end time:%s\n",info.end_time);
		printf("days:%s\n",info.days);
		printf("order type:%s\n",info.order_type_name);
		printf("order type:%s\n",info.order_type);
		printf("channel:%s\n",info.channel);
		printf("prog:%d\n",info.antenna_prog_id);
		printf("freq:%d\n",info.freq);
		printf("azimuth:%s\n",info.azimuth);
		printf("actual power:%s\n",info.actual_power);
		printf("op status:%s\n",info.op_status);
		printf("trans name:%s\n",info.trans_name);
		printf("ant:%s\n",info.ant_used_code);
		printf("station name:%s\n",info.station_name);
		printf("prog desc:%s\n",info.prog_desc);
		printf("program name:%s\n",info.program_name);
		printf("ant prog desc:%s\n",info.ant_prog_desc);
		printf("feedback:%s\n",info.feedback_status);
		printf("acutlal start:%s\n",info.actual_start);
		printf("mod:%s\n",info.mod);
	}
	order_page_destroy(&op_tmp);
}


//**********************************************************************************************
// regex func
//**********************************************************************************************
char* regex_find(char* dst,char* content,char* regex){
        regex_t reg;
        regmatch_t matchptr[1];
        char *tmp=content,*result=NULL;
        int ret;
        if( (ret=regcomp(&reg,regex,REG_EXTENDED|REG_NEWLINE)) ){return NULL;}
        while( (ret=regexec(&reg,tmp,1,matchptr,0)) == 0 ){ // find a last match
                result=tmp+matchptr[0].rm_so;
                tmp=tmp+matchptr[0].rm_eo;
        }
        if(result!=NULL){
                tmp=stpncpy(dst,result,matchptr[0].rm_eo-matchptr[0].rm_so);
                *tmp='\0';
                regfree(&reg);
                return dst;
        }
        else{
                regfree(&reg);
                return NULL;
        }
}
